2.3 数据可视化

🎯 学习目标

通过个人支出图表项目,掌握Matplotlib数据可视化技术

📝 项目预览:个人支出图表

我们将创建一个能够生成各种支出图表的工具,通过这个项目学习:

  • Matplotlib基础图表绘制
  • 图表美化和自定义
  • 多种图表类型的应用场景
  • 数据可视化的最佳实践
  • 交互式图表创建

1. Matplotlib简介

什么是Matplotlib?

Matplotlib是Python中最流行的数据可视化库,可以创建各种静态、交互式图表。

为什么需要数据可视化?

  • 直观理解:图表比数字更易于理解
  • 发现规律:可视化能揭示数据中的模式
  • 有效沟通:图表是数据报告的重要部分
  • 决策支持:基于可视化结果做出更好决策

安装Matplotlib

pip install matplotlib

2. 基础图表绘制

基本绘图流程

import matplotlib.pyplot as plt

# 1. 准备数据
categories = ['餐饮', '交通', '购物', '娱乐']
amounts = [150, 80, 200, 120]

# 2. 创建图表
plt.figure(figsize=(10, 6))  # 设置图表大小

# 3. 绘制柱状图
plt.bar(categories, amounts)

# 4. 设置图表属性
plt.title('月度支出情况')
plt.xlabel('支出类别')
plt.ylabel('金额(元)')

# 5. 显示图表
plt.show()

中文字体设置

# 设置中文字体(解决中文显示问题)
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False    # 用来正常显示负号

# 如果SimHei不可用,可以尝试其他字体
# plt.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'SimSun', 'Arial']

3. 常用图表类型

柱状图 (Bar Chart)

# 基本柱状图
plt.bar(categories, amounts, color='skyblue')
plt.title('支出类别柱状图')
plt.xlabel('类别')
plt.ylabel('金额')
plt.show()

# 分组柱状图
import numpy as np

# 多个月份的数据
months = ['1月', '2月', '3月']
data = np.array([
    [150, 80, 200, 120],  # 1月
    [180, 90, 150, 100],  # 2月
    [120, 70, 180, 140]   # 3月
])

x = np.arange(len(categories))
width = 0.25

for i, month in enumerate(months):
    plt.bar(x + i*width, data[i], width, label=month)

plt.legend()
plt.show()

饼图 (Pie Chart)

# 基本饼图
plt.pie(amounts, labels=categories, autopct='%1.1f%%')
plt.title('支出比例分布')
plt.axis('equal')  # 确保饼图是圆形
plt.show()

# 带突出效果的饼图
explode = [0.1, 0, 0, 0]  # 突出显示第一个部分
plt.pie(amounts, labels=categories, explode=explode, autopct='%1.1f%%')
plt.title('支出比例分布(突出显示最大项)')
plt.show()

折线图 (Line Chart)

# 时间序列折线图
dates = ['1日', '5日', '10日', '15日', '20日', '25日', '30日']
daily_expenses = [50, 80, 120, 60, 150, 90, 70]

plt.plot(dates, daily_expenses, marker='o', linewidth=2)
plt.title('每日支出趋势')
plt.xlabel('日期')
plt.ylabel('金额(元)')
plt.grid(True, alpha=0.3)
plt.show()

散点图 (Scatter Plot)

# 散点图示例
np.random.seed(42)
x = np.random.rand(50) * 100  # 随机x值
y = np.random.rand(50) * 200  # 随机y值

plt.scatter(x, y, alpha=0.6)
plt.title('支出散点图')
plt.xlabel('变量X')
plt.ylabel('变量Y')
plt.show()

4. 图表美化

颜色和样式

# 使用颜色映射
colors = plt.cm.Set3(np.linspace(0, 1, len(categories)))
plt.bar(categories, amounts, color=colors)
plt.title('彩色柱状图')
plt.show()

# 自定义颜色
custom_colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4']
plt.bar(categories, amounts, color=custom_colors)
plt.title('自定义颜色柱状图')
plt.show()

添加数值标签

# 在柱状图上显示数值
bars = plt.bar(categories, amounts, color='lightblue')

for bar, amount in zip(bars, amounts):
    plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 2, 
             f'{amount}元', ha='center', va='bottom')

plt.title('带数值标签的柱状图')
plt.show()

网格和样式

# 添加网格
plt.bar(categories, amounts)
plt.grid(axis='y', alpha=0.3)  # 只在y轴显示网格
plt.title('带网格的柱状图')
plt.show()

# 使用样式
plt.style.use('ggplot')  # 使用ggplot样式
plt.bar(categories, amounts)
plt.title('使用ggplot样式的柱状图')
plt.show()

5. 多子图布局

创建多个子图

# 创建2x2的子图布局
fig, axes = plt.subplots(2, 2, figsize=(12, 10))

# 第一个子图:柱状图
axes[0, 0].bar(categories, amounts)
axes[0, 0].set_title('柱状图')

# 第二个子图:饼图
axes[0, 1].pie(amounts, labels=categories, autopct='%1.1f%%')
axes[0, 1].set_title('饼图')

# 第三个子图:折线图
axes[1, 0].plot(dates, daily_expenses, marker='o')
axes[1, 0].set_title('折线图')
axes[1, 0].tick_params(axis='x', rotation=45)

# 第四个子图:散点图
axes[1, 1].scatter(x, y, alpha=0.6)
axes[1, 1].set_title('散点图')

plt.tight_layout()  # 自动调整布局
plt.show()

6. 实际应用案例

支出分析图表

def create_expense_analysis():
    """创建完整的支出分析图表"""
    
    # 准备数据
    categories = ['餐饮', '交通', '购物', '娱乐', '学习', '其他']
    amounts = [450, 240, 600, 360, 300, 150]
    
    # 创建图表
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
    
    # 左侧:柱状图
    bars = ax1.bar(categories, amounts, color=plt.cm.Pastel1(range(len(categories))))
    ax1.set_title('月度支出柱状图', fontsize=14, fontweight='bold')
    ax1.set_ylabel('金额(元)')
    ax1.grid(axis='y', alpha=0.3)
    
    # 添加数值标签
    for bar, amount in zip(bars, amounts):
        ax1.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 10, 
                f'{amount}元', ha='center', va='bottom', fontweight='bold')
    
    # 右侧:饼图
    wedges, texts, autotexts = ax2.pie(amounts, labels=categories, autopct='%1.1f%%',
                                      startangle=90, colors=plt.cm.Set3(np.linspace(0, 1, len(categories))))
    ax2.set_title('支出比例分布', fontsize=14, fontweight='bold')
    
    # 美化饼图文本
    for autotext in autotexts:
        autotext.set_color('white')
        autotext.set_fontweight('bold')
    
    plt.tight_layout()
    plt.show()
    
    # 打印统计信息
    total = sum(amounts)
    max_category = categories[amounts.index(max(amounts))]
    print(f"总支出: {total}元")
    print(f"最大支出类别: {max_category} ({max(amounts)}元)")
    print(f"平均每类支出: {total/len(categories):.1f}元")

时间趋势分析

def create_trend_analysis():
    """创建时间趋势分析图表"""
    
    # 模拟3个月的数据
    months = ['1月', '2月', '3月']
    categories = ['餐饮', '交通', '购物']
    
    data = np.array([
        [450, 240, 600],  # 1月
        [480, 260, 550],  # 2月
        [420, 220, 650]   # 3月
    ])
    
    # 创建折线图
    plt.figure(figsize=(12, 8))
    
    for i, category in enumerate(categories):
        plt.plot(months, data[:, i], marker='o', linewidth=2, label=category)
    
    plt.title('前三个月支出趋势', fontsize=16, fontweight='bold')
    plt.xlabel('月份')
    plt.ylabel('金额(元)')
    plt.legend()
    plt.grid(True, alpha=0.3)
    plt.show()
    
    # 创建堆叠面积图
    plt.figure(figsize=(12, 8))
    plt.stackplot(months, data.T, labels=categories, alpha=0.8)
    plt.title('支出堆叠面积图', fontsize=16, fontweight='bold')
    plt.xlabel('月份')
    plt.ylabel('金额(元)')
    plt.legend(loc='upper left')
    plt.show()

7. 图表保存和导出

保存图表

# 保存为图片
plt.figure(figsize=(10, 6))
plt.bar(categories, amounts)
plt.title('月度支出')
plt.savefig('monthly_expenses.png', dpi=300, bbox_inches='tight')
plt.savefig('monthly_expenses.pdf')  # 保存为PDF
print("图表已保存")

高质量导出设置

# 高质量导出设置
plt.figure(figsize=(10, 6), dpi=300)  # 高分辨率
plt.bar(categories, amounts, color='lightblue', edgecolor='black', linewidth=1)
plt.title('高质量支出图表', fontsize=14, fontweight='bold')
plt.xlabel('支出类别', fontsize=12)
plt.ylabel('金额(元)', fontsize=12)
plt.grid(axis='y', alpha=0.3)

# 保存为高质量图片
plt.savefig('high_quality_chart.png', dpi=300, bbox_inches='tight', 
            facecolor='white', edgecolor='none')
plt.show()

8. 交互式可视化

简单的交互功能

def interactive_chart():
    """交互式图表创建"""
    
    while True:
        print("\n请选择图表类型:")
        print("1. 柱状图")
        print("2. 饼图") 
        print("3. 退出")
        
        choice = input("请输入选择: ")
        
        if choice == '1':
            # 获取用户数据
            categories = input("请输入类别(用空格分隔): ").split()
            amounts = [float(x) for x in input("请输入金额(用空格分隔): ").split()]
            
            plt.bar(categories, amounts)
            plt.title('自定义柱状图')
            plt.show()
            
        elif choice == '2':
            categories = input("请输入类别(用空格分隔): ").split()
            amounts = [float(x) for x in input("请输入金额(用空格分隔): ").split()]
            
            plt.pie(amounts, labels=categories, autopct='%1.1f%%')
            plt.title('自定义饼图')
            plt.show()
            
        elif choice == '3':
            break
        else:
            print("无效选择")

📋 个人支出图表完整代码解析

让我们看看项目中的关键代码:

import matplotlib.pyplot as plt
import numpy as np

def basic_bar_chart(categories, amounts):
    """创建基本柱状图"""
    plt.figure(figsize=(10, 6))
    
    # 设置中文字体
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    
    bars = plt.bar(categories, amounts, color='lightblue')
    
    # 添加数值标签
    for bar, amount in zip(bars, amounts):
        plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 2, 
                f'{amount}元', ha='center', va='bottom')
    
    plt.title('月度支出情况')
    plt.xlabel('支出类别')
    plt.ylabel('金额(元)')
    plt.grid(axis='y', alpha=0.3)
    plt.tight_layout()
    plt.show()

def main():
    """主程序"""
    # 示例数据
    categories = ['餐饮', '交通', '购物', '娱乐', '学习']
    amounts = [450, 240, 600, 360, 300]
    
    print("=== 个人支出图表工具 ===")
    print(f"支出数据: {dict(zip(categories, amounts))}")
    
    basic_bar_chart(categories, amounts)
    
    # 计算统计信息
    total = sum(amounts)
    max_amount = max(amounts)
    max_category = categories[amounts.index(max_amount)]
    
    print(f"总支出: {total}元")
    print(f"最大支出: {max_category} {max_amount}元")
    print(f"平均每类支出: {total/len(amounts):.1f}元")

if __name__ == "__main__":
    main()

🎯 学习要点总结

  1. 基础绘图plt.plot(), plt.bar(), plt.pie(), plt.scatter()
  2. 图表美化:颜色、标签、标题、网格、样式
  3. 字体设置:解决中文显示问题的配置
  4. 多子图plt.subplots() 创建复杂布局
  5. 数值标注:在图表上显示具体数值
  6. 图表保存plt.savefig() 导出高质量图片
  7. 交互功能:根据用户输入动态创建图表
  8. 最佳实践:图表设计原则和可视化规范

💡 练习建议

  1. 运行代码:打开 code/第二阶段/2.3_个人支出图表.py 体验功能
  2. 修改样式:尝试不同的颜色、字体、布局
  3. 添加功能:实现更多图表类型和交互功能
  4. 真实数据:使用自己的支出数据创建图表
  5. 报告生成:创建包含多个图表的完整报告

🚀 数据可视化的价值

  1. 洞察发现:通过可视化发现数据中的模式和异常
  2. 故事讲述:用图表讲述数据背后的故事
  3. 决策支持:基于可视化结果做出更好的决策
  4. 沟通效率:图表比表格更易于理解和记忆
  5. 专业形象:高质量的可视化提升专业形象

🚀 下一步

掌握数据可视化后,你可以继续学习:

  • 第三阶段:机器学习基础
  • 高级可视化:Seaborn、Plotly等高级库
  • 仪表板开发:创建交互式数据仪表板
  • 实际项目:用可视化技术解决实际问题

记住:一张好的图表胜过千言万语,可视化是数据科学中最重要的沟通工具!


学习愉快!多练习图表绘制,这是数据科学家的必备技能!

« 上一篇 2.2 Pandas数据分析 下一篇 » 3.1 机器学习基础